<?php

/**
 * CCoreMimeUtils
 *
 * @author Usenko Timur <usenko.timur@gmail.com>
 * @package mime
 */

CCore::Using('base.utils');

/**
 * @package mime
 */
class CCoreMimeUtils
{
	/**
	 * @param string $sBodyString
	 * @param string &$sEndBuffer
	 * @return string
	 */
	public static function InlineNullDecode($sBodyString, &$sEndBuffer)
	{
		$sTrimEndBuffer = '';
		return $sBodyString;
	}

	/**
	 * @param string $sBase64String
	 * @param string &$sEndBuffer
	 * @return string
	 */
	public static function InlineBase64Decode($sBase64String, &$sEndBuffer)
	{
		$sEndBuffer = '';
		$sBase64String = str_replace(array("\r", "\n", "\t"), '', $sBase64String);
		$iBase64StringLen = strlen($sBase64String);
		$iBase64StringNormLenX4 = floor($iBase64StringLen / 4) * 4;
		if ($iBase64StringNormLenX4 < $iBase64StringLen)
		{
			$sEndBuffer = substr($sBase64String, $iBase64StringNormLenX4);
			$sBase64String = substr($sBase64String, 0, $iBase64StringNormLenX4);
		}
		return base64_decode($sBase64String);
	}

	/**
	 * @param string $sQuotedPrintableString
	 * @param string &$sEndBuffer
	 * @return string
	 */
	public static function InlineQuotedPrintableDecode($sQuotedPrintableString, &$sEndBuffer)
	{
		$sEndBuffer = '';
		$sQuotedPrintableLen = strlen($sQuotedPrintableString);
		$iLastSpace = strrpos($sQuotedPrintableString, ' ');
		if (false !== $iLastSpace && $iLastSpace + 1 < $sQuotedPrintableLen)
		{
			$sEndBuffer = substr($sQuotedPrintableString, $iLastSpace + 1);
			$sQuotedPrintableString = substr($sQuotedPrintableString, 0, $iLastSpace + 1);
		}
		return quoted_printable_decode($sQuotedPrintableString);
	}

	/**
	 * @param string $sEncodedString
	 * @param string &$sEndBuffer
	 * @return string
	 */
	public static function InlineConvertDecode($sEncodedString, &$sEndBuffer, $sFromEncoding, $sToEncoding)
	{
		$sEndBuffer = '';
		$sQuotedPrintableLen = strlen($sEncodedString);
		$iLastSpace = strrpos($sEncodedString, ' ');
		if (false !== $iLastSpace && $iLastSpace + 1 < $sQuotedPrintableLen)
		{
			$sEndBuffer = substr($sEncodedString, $iLastSpace + 1);
			$sEncodedString = substr($sEncodedString, 0, $iLastSpace + 1);
		}
		return CCoreBaseUtils::ConvertEncoding($sEncodedString, $sFromEncoding, $sToEncoding);
	}

	/**
	 * @return string
	 */
	public static function GetInlineDecodeFunctionName($sContentTransferEncoding)
	{
		$sFunctionName = 'InlineNullDecode';
		switch (strtolower($sContentTransferEncoding))
		{
			case 'base64':
				$sFunctionName = 'InlineBase64Decode';
				break;
			case 'quoted-printable':
				$sFunctionName = 'InlineQuotedPrintableDecode';
				break;
		}

		return $sFunctionName;
	}

	/**
	 * @todo
	 * @param string $sText
	 * @param string $sOutputCharset = C_MIME_CHARSET_UTF8
	 * @return string
	 */
	public static function DecodeHeaderValue($sHeaderValue, $sInputCharset, $sOutputCharset = C_MIME_CHARSET_UTF8)
	{
		CCore::CheckTypes(array('$sHeaderValue', '$sInputCharset', '$sOutputCharset'));

		$sValue = CCoreBaseUtils::ConvertEncoding($sHeaderValue, $sInputCharset, $sOutputCharset);
		
		$sValue = preg_replace('/\?=[\s]{1,5}=\?/m', '?==?', $sValue);
		$sValue = preg_replace('/[\r\n\t]+/m', ' ', $sValue); #TODO: analyze

		$aEncodeArray = self::_searchEncodedPlaces($sValue);

		for ($i = 0, $c = count($aEncodeArray); $i < $c; $i++)
		{
			$aTempArr = self::_QBDecodeString($aEncodeArray[$i]);
			if (2 === count($aTempArr) && strlen($aTempArr[0]) > 0)
			{
				$sValue = str_replace($aEncodeArray[$i],
					CCoreBaseUtils::ConvertEncoding($aTempArr[1], $aTempArr[0], $sOutputCharset),
					$sValue);
			}
			unset($aTempArr);
		}

		return $sValue;
	}

	/**
	 * @param string $sHeaderValuePart
	 * @return array
	 */
	private static function _QBDecodeString($sHeaderValuePart)
	{
		CCore::CheckTypes(array('$sHeaderValuePart'));

		$aReturn = array('', $sHeaderValuePart);
		if ('=?' === substr(trim($sHeaderValuePart), 0, 2))
		{
			$iPos = strpos($sHeaderValuePart, '?', 2);
			$aReturn[0] = substr($sHeaderValuePart, 2, $iPos - 2);
			$sEncType = strtolower($sHeaderValuePart{$iPos + 1});
			switch ($sEncType)
			{
				case 'q':
					$sHeaderValuePart = str_replace('_', ' ', $sHeaderValuePart);
					$aReturn[1] = quoted_printable_decode(substr($sHeaderValuePart, $iPos + 3, strlen($sHeaderValuePart) - $iPos - 5));
					break;
				case 'b':
					$aReturn[1] = base64_decode(substr($sHeaderValuePart, $iPos + 3, strlen($sHeaderValuePart) - $iPos - 5));
					break;
			}
		}

		return $aReturn;
	}

	/**
	 * @param string $sHeaderValue
	 * @return array
	 */
	private static function _searchEncodedPlaces($sHeaderValue)
	{
		CCore::CheckTypes(array('$sHeaderValue'));

		$aMatch = array('');
		preg_match_all('/=\?[^\?]+\?[q|b|Q|B]\?[^\?]*(\?=)/', $sHeaderValue, $aMatch);

		if (isset($aMatch[0]))
		{
			for ($i = 0, $c = count($aMatch[0]); $i < $c; $i++)
			{
				if (isset($aMatch[0][$i]))
				{
					$iPos = @strpos($aMatch[0][$i], '*');
					if (false !== $iPos)
					{
						$aMatch[0][$i][0] = substr($aMatch[0][$i][0], 0, $iPos);
					}
				}
			}
			
			return $aMatch[0];
		}

		return array();
	}
}
